package dao;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import business.Defi;


public class DaoDefi {
	/* ------------------------------------------------ REQUETES PRECOMPILEES */
	private static CallableStatement statementGetDefi = null;
	private static CallableStatement statementGetDefisFaits = null;
	private static CallableStatement statementGetDefisRecus = null;
	private static CallableStatement statementAjouterDefi = null;
	private static CallableStatement statementAccepterDefi = null;
	private static CallableStatement statementRefuserDefi = null;


	/* --------------------------------------------------------- CONSTRUCTEUR */
	static {
		try {
			statementGetDefi = DbConnection.getInstance().prepareCall("{call getDefi(?)}");
			statementGetDefisFaits = DbConnection.getInstance().prepareCall("{call getDefisFaits(?)}");
			statementGetDefisRecus = DbConnection.getInstance().prepareCall("{call getDefisRecus(?)}");
			statementAjouterDefi = DbConnection.getInstance().prepareCall("{call ajouterDefi(?, ?, ?)}");
			statementAccepterDefi = DbConnection.getInstance().prepareCall("{call accepterDefi(?, ?, ?, ?, ?)}");
			statementRefuserDefi = DbConnection.getInstance().prepareCall("{call refuserDefi(?)}");
		}
		catch(SQLException e) {
			e.printStackTrace();
		}
	}


	/* -------------------------------------------------------------- METHODE */
	public static Defi getDefi(int id_defi) {
		Defi defi = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementGetDefi) {
				statementGetDefi.setInt(1, id_defi);
				
				rs = statementGetDefi.executeQuery();
			}
			
			if(rs != null && rs.last()) {
				if(rs.getRow() == 1) {
					defi = new Defi(
							rs.getInt("id_defi"),
							rs.getInt("fk_id_demandeur"),
							rs.getInt("fk_id_cible"),
							rs.getInt("fk_id_pariDemandeur"),
							rs.getInt("fk_id_pariCible"),
							rs.getInt("fk_id_pariHistoriqueDemandeur"),
							rs.getInt("fk_id_pariHistoriqueCible"),
							rs.getInt("etat"));
				}
				else {
					System.err.println("DaoDefi.getDefi(" + id_defi + ") : plusieurs résultats.");
				}
			}
			else {
				System.err.println("DaoDefi.getDefi(" + id_defi + ") : aucun résultat.");
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return null;
		}
		
		return defi;
	}
	

	public static List<Defi> getDefisFaits(int id_utilisateur) {
		List<Defi> defis = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementGetDefisFaits) {
				statementGetDefisFaits.setInt(1, id_utilisateur);
				
				rs = statementGetDefisFaits.executeQuery();
			}
			
			if(rs != null) {
				defis = new ArrayList<Defi>();
				
				while(rs.next()) {
					defis.add(new Defi(
							rs.getInt("id_defi"),
							rs.getInt("fk_id_demandeur"),
							rs.getInt("fk_id_cible"),
							rs.getInt("fk_id_pariDemandeur"),
							rs.getInt("fk_id_pariCible"),
							rs.getInt("fk_id_pariHistoriqueDemandeur"),
							rs.getInt("fk_id_pariHistoriqueCible"),
							rs.getInt("etat")));
				}
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
		}
		
		return defis;
	}


	public static List<Defi> getDefisRecus(int id_utilisateur) {
		List<Defi> defis = null;
		
		try {
			ResultSet rs = null;
			
			synchronized(statementGetDefisRecus) {
				statementGetDefisRecus.setInt(1, id_utilisateur);
				
				rs = statementGetDefisRecus.executeQuery();
			}
			
			if(rs != null) {
				defis = new ArrayList<Defi>();
				
				while(rs.next()) {
					defis.add(new Defi(
							rs.getInt("id_defi"),
							rs.getInt("fk_id_demandeur"),
							rs.getInt("fk_id_cible"),
							rs.getInt("fk_id_pariDemandeur"),
							rs.getInt("fk_id_pariCible"),
							rs.getInt("fk_id_pariHistoriqueDemandeur"),
							rs.getInt("fk_id_pariHistoriqueCible"),
							rs.getInt("etat")));
				}
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
		}
		
		return defis;
	}


	public static boolean ajouterDefi(int fk_id_demandeur, int fk_id_target, int fk_id_pariDemandeur) {
		try {
			synchronized(statementAjouterDefi) {
				statementAjouterDefi.setInt(1, fk_id_demandeur);
				statementAjouterDefi.setInt(2, fk_id_target);
				statementAjouterDefi.setInt(3, fk_id_pariDemandeur);
				
				statementAjouterDefi.execute();
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}


	public static boolean accepterDefi(int id_defi, int mise, int retard) {
		try {
			Date heurePari = new Date(); //TODO voir pour récupérer l'heure actuelle depuis les serveurs de la SNCF
			Date arriveeTheorique = DaoPassageTrainTheorique.getPassageTrainTheorique(DaoPari.getPari(DaoDefi.getDefi(id_defi).getFk_id_pariDemandeur()).getFk_id_passageTrainTheorique()).getArriveeTheorique();
			long msPassageTrain = arriveeTheorique.getTime();
			int minAvantPassage = (int) (msPassageTrain - heurePari.getTime()) / (60000);
			double coefficient = (1.0 + (((double) retard)/3.0)) * (1.0 + (((double) Math.max(0.0, (minAvantPassage-10.0)))/50.0));
			int gainPossible = (int) (mise * coefficient);
			
			synchronized(statementAccepterDefi) {
				statementAccepterDefi.setInt(1, id_defi);
				statementAccepterDefi.setInt(2, mise);
				statementAccepterDefi.setInt(3, retard);
				statementAccepterDefi.setTimestamp(4, new java.sql.Timestamp(heurePari.getTime()));
				statementAccepterDefi.setInt(5, gainPossible);
				
				statementAccepterDefi.execute();
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}


	public static boolean refuserDefi(int id_defi) {
		try {
			synchronized(statementRefuserDefi) {
				statementRefuserDefi.setInt(1, id_defi);
				
				statementRefuserDefi.execute();
			}
		}
		catch(SQLException e) {
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}
}
